import sys
import os
relativePathToScript = os.path.split(sys.argv[0])[0]
relativePathToParent = os.path.join(relativePathToScript, "..")
sys.path.append(relativePathToParent)
import unittest
import pygame
from interblock import Board
from pieces import InvalidPositionError, Single, Tee, Line, MoveWithoutStartingError, RotateWithoutStartingError
##import helpers
##helpers.prefix = relativePathToParent

class TestPieces(unittest.TestCase):
    def setUp(self):
        pygame.init()
        pygame.display.set_mode((100, 100))
        self.board = Board(250, 250)
        self.tee = Tee(self.board, 'blue', 0, 0)
    
    def testMovingPieceToNonStartingCell(self):
        board = Board(100, 100)
        single = Single(board, "blue", 10, 10)
        assert single.startMoving() == True
        single.moveBy((300, 300))
        single.stopMoving()
        assert single.rect.topleft == (10, 10)

    def testMovingPieceInScratchSpace(self):
        board = Board(100, 100)
        piece = Tee(board, "blue", 0, 0)
        assert piece.startMoving() == True
        piece.moveBy((300, 3))
        piece.stopMoving()
        assert piece.rect.topleft == (300, 3)

    def testMovingPiecePartlyOntoBoard(self):
        board = Board(100, 100)
        piece = Line(board, "blue", 0, 0)
        assert piece.startMoving() == True
        piece.moveBy((50, 200))
        piece.stopMoving()
        assert piece.rect.topleft == (0, 0)

    def testMovingPieceOntoStartCell(self):
        board = Board(250, 250)
        piece = Line(board, "blue", 0, 0)
        assert piece.startMoving() == True
        piece.moveBy((250, 720))
        piece.stopMoving()
        assert piece.rect.topleft == (250, 725)
        assert board.grid[0][19] == 'b'
    
    def testAddingPieceNextToSameColorPiece(self):
        board = Board(250, 250)
        single = Single(board, "blue", 0, 0)
        assert single.startMoving() == True
        single.moveBy((250, 725))
        single.stopMoving()
        piece = Line(board, "blue", 0, 0)
        assert piece.startMoving() == True
        piece.moveBy((275, 725))
        piece.stopMoving()
        assert piece.rect.topleft == (0, 0)
    
    def testAddingPieceInValidCell(self):
        board = Board(250, 250)
        single = Single(board, "blue", 0, 0)
        assert single.startMoving() == True
        single.moveBy((250, 725))
        single.stopMoving()
        piece = Line(board, "blue", 0, 0)
        assert piece.startMoving() == True
        piece.moveBy((275, 700))
        piece.stopMoving()
        assert piece.rect.topleft == (275, 700)
    
    def testMovingPieceOffOfBoard(self):
        board = Board(250, 250)
        single = Single(board, "blue", 0, 0)
        assert single.startMoving() == True
        single.moveBy((250, 725))
        single.stopMoving()
        assert single.startMoving() == False
        assert single.rect.topleft == (250, 725)
    
    def testMovingPieceWithoutStarting(self):
        self.assertRaises(MoveWithoutStartingError, self.tee.moveBy, (100, 100))
    
    def testRotatingPieceWithoutStarting(self):
        self.assertRaises(RotateWithoutStartingError, self.tee.rotateBy, 90)
    
    def testCreatePieceWithDefaultSize(self):
        board = Board(250, 250)
        single = Single(board, "blue", 0, 0)
        assert single.rect.width == 25
        assert single.rect.height == 25
    
    def testCreatePieceWithNondefaultSize(self):
        board = Board(250, 250)
        piece = Line(board, "blue", 0, 0, size=10)
        assert piece.rect.height == 10
        assert piece.rect.width == 50
    
    def testRotatingPiece270Degrees(self):
        # = 90 degrees clockwise
        assert self.tee.rect.height == self.tee.blockSize * 2
        assert self.tee.rect.width == self.tee.blockSize * 3
        assert self._listContainsOnly(self.tee.blocks, [(0, 0), (1, 0), (2, 0), (1, 1)]) is True
        self.tee.startRotating()
        self.tee.rotateBy(270)
        self.tee.stopRotating()
        assert self.tee.rect.height == self.tee.blockSize * 3
        assert self.tee.rect.width == self.tee.blockSize * 2
        assert self._listContainsOnly(self.tee.blocks, [(1, 0), (0, 1), (1, 1), (1, 2)]) is True
    
    def testTwo90DegreeRotations(self):
        self.tee.startMoving()
        self.tee.moveBy((100, 100))
        self.tee.stopMoving()
        self.tee.startRotating()
        self.tee.rotateBy(90)
        self.tee.stopRotating()
        self.tee.startRotating()
        self.tee.rotateBy(90)
        self.tee.stopRotating()
        assert self.tee.rect.left == 100
        assert self.tee.rect.top == 100
    
    def _listContainsOnly(self, list, contents):
        if len(list) != len(contents):
            return False
        for element in contents:
            if element not in list:
                return False
        return True
    
    def testPieceColors(self):
        for color in ["red", "yellow", "green", "blue"]:
            piece = Line(self.board, color, 0, 0)
    
    def testFlipPiece(self):
        assert self.tee.rect.width == 3 * self.tee.blockSize
        assert self.tee.rect.height == 2 * self.tee.blockSize
        assert self._listContainsOnly(self.tee.blocks, [(0, 0), (1, 0), (2, 0), (1, 1)]) is True
        self.tee.flipVertically()
        assert self.tee.rect.width == 3 * self.tee.blockSize
        assert self.tee.rect.height == 2 * self.tee.blockSize
        assert self._listContainsOnly(self.tee.blocks, [(0, 1), (1, 1), (2, 1), (1, 0)]) is True

    def testFlipRotatedPiece(self):
        self.tee.startRotating()
        self.tee.rotateBy(90)
        self.tee.stopRotating()
        assert self.tee.rect.width == 2 * self.tee.blockSize
        assert self.tee.rect.height == 3 * self.tee.blockSize
        assert self._listContainsOnly(self.tee.blocks, [(0, 0), (0, 1), (0, 2), (1, 1)]) is True
        self.tee.flipVertically()
        assert self.tee.rect.width == 2 * self.tee.blockSize
        assert self.tee.rect.height == 3 * self.tee.blockSize
        assert self._listContainsOnly(self.tee.blocks, [(0, 0), (0, 1), (0, 2), (1, 1)]) is True


if __name__ == "__main__":
    unittest.main()
